#include "Epoller.h"
#include "Channel.h"
#include "Eventloop.h"

namespace liu
{

	Epoller::Epoller(Eventloop* pLoop)
		:m_pOwnerLoop(pLoop),
		m_EpollFd(epoll_create1(EPOLL_CLOEXEC)),
		m_vecEpollEvents(INIT_EVENT_LIST_SIZE)
	{
		cout << debug_time() << "Create epollfd:[" << m_EpollFd << "]." << endl;
	}

	Epoller::~Epoller()
	{
		::close(m_EpollFd);
	}

	void Epoller::PollWait(int timeoutMs, VEC_CHANNEL_PTR& activeChannels)
	{
		int numFds = ::epoll_wait(m_EpollFd, &(*m_vecEpollEvents.begin()),
			static_cast<int>(m_vecEpollEvents.size()),
			timeoutMs);

		if (numFds > 0)
		{	
			fillActiveChannels(numFds, activeChannels);
		}
	}

	void Epoller::UpdateChannel(Channel* pChannel)
	{
		update(EPOLL_CTL_ADD, pChannel);
	}

	void Epoller::RemoveChannel(Channel* pChannel)
	{

	}

	void Epoller::fillActiveChannels(int numEvents, VEC_CHANNEL_PTR& activeChannels)
	{	
		for (int i = 0; i < numEvents; ++i)
		{
			Channel* pTempChannel = static_cast<Channel*>(m_vecEpollEvents[i].data.ptr);
			int fd = pTempChannel->m_fd;
			pTempChannel->m_revents = (m_vecEpollEvents[i].events);
			activeChannels.push_back(pTempChannel);
		}
	}

	void Epoller::update(int optype, Channel* pChannel)
	{
		RUN_TRACE;
		struct epoll_event event;
		bzero(&event, sizeof event);
		event.events = pChannel->m_events;
		event.data.ptr = pChannel;
		int fd = pChannel->m_fd;	
		
		::epoll_ctl(m_EpollFd, optype, fd, &event);

		cout << debug_time() << "epollfd:[" << m_EpollFd << "] add fd:[" << fd << "] with read event." << endl;
	}
}

